home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
events.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
372 lines
/*
* $Id: events.c,v 0.91 1994/02/20 00:53:24 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* All events service routines.
*
* The program works by wrapping fl_qread with bit_qread
* so that some events are consumed via installed handlers before
* ever reaching the calling routine. This allows any function to
* implement its own specialized mouse/keyboard sequence. In addition,
* events like REDRAW, INPUTCHANGE etc., which always demand
* immediate response, need not be handled by any of the functions
* that calls bit_qread.
*
*/
#if !defined(lint) && defined(F_ID)
char *id_evt = "$Id: events.c,v 0.91 1994/02/20 00:53:24 zhao Pre-Release $";
#endif
#include "bit.h"
#include "extern.h"
/*************************************************************
* GLQhandler takes (dev, val) pair, and returns 0 if the Q event
* is handled (consumed), else return the input for other handlers.
*
* Installed handler handles user events, like mouse click etc
* in a dynamically changeable way, for exampe, in main
* leftmouse advance the flist pointer while in text, it moves
* the location of text.
***************************************************************/
#define MAXGLQH 3 /* max number of handlers */
static GLQhandler gl_q_handler[MAXGLQH];
/*************************************************************
* Install a handler. Installing the same handler more than
* once is the same as installing once.
**************************************************************/
void
install_GLQ_handler(GLQhandler glh)
{
GLQhandler *wmei = gl_q_handler, *wmef = wmei + MAXGLQH;
/* search for an empty slot */
for (; wmei < wmef && *wmei && *wmei != glh; wmei++)
;
if (wmei == wmef)
{
Bark("GLQhandler", "Can't install -- out of bounds");
return;
}
*wmei = glh;
}
/***********************************************************
* remove a handler
************************************************************/
void
remove_GLQ_handler(GLQhandler glh)
{
GLQhandler *wmei = gl_q_handler, *wmef;
for (wmef = wmei + MAXGLQH; --wmef >= wmei && *wmef != glh;)
;
if (wmef < wmei) /* not found */
{
M_err("GLQhandler", "Can't remove -- no existent handler");
return;
}
/* remove it */
*wmef = 0;
}
/*************************************************************
* handle events (dev, short) by calling all installed handlers
* If the event is consumed, return 0
****************************************************************/
long
handle_GLQ(long dev, short val)
{
long h = dev;
GLQhandler *wmei = gl_q_handler, *wmef;
M_info("HandleGLQ", "dev=%ld val=%d", dev, val);
if (!dev || !val)
return 0;
wmef = wmei + MAXGLQH;
do
{
if (*wmei)
h = (*wmei) (dev, val);
wmei++;
}
while (h == dev && wmei < wmef);
return h;
}
/*******************************************************************
* Return the number of handlers. useful for debuging
********************************************************************/
int
total_GLQ_handler(void)
{
GLQhandler *wmei = gl_q_handler, *wmef;
int i;
for (i = 0, wmef = wmei + MAXGLQH; wmei < wmef; wmei++)
if (*wmei)
i++;
return i;
}
/****************************************************************
* handle_const_q handles the events that are not used by user
* routines and events that need to be handled in the same way,
* in other words, other routines never see the events handled
* by handle_const_q.
*
* If the event dev is not meant for const_q, return it.
*****************************************************************/
long
handle_const_q(long dev, short val)
{
long ret = 0;
if (!val)
return 0;
#ifdef MDEBUG
M_info("handle_const_q", "dev = %d val=%d", (int) dev, val);
#endif
switch (dev)
{
case REDRAW:
repaint(imgptr, val);
break;
case INPUTCHANGE:
if (val > 0)
set_current_window(val);
break;
case WINQUIT:
case WINSHUT:
if (val == win_id)
clean_up();
break;
case PAUSEKEY:
pausing(imgptr);
break;
case WINFREEZE:
if (val == win_id)
bit_iconify();
else
ret = dev;
break;
case REDRAWICONIC:
if (val == win_id)
bit_draw_icon(win_id);
else
ret = dev;
break;
case WINTHAW:
if (val == win_id)
bit_de_iconify();
else
ret = dev;
break;
case MKEY:
show_info_window(-1, -1, -1, -1, 1);
break;
case SKEY:
slideshow_off();
break;
default: /* not consumed */
ret = dev;
break;
}
return ret;
}
/*****************************************************************
* Global routine to handle an event. const Q is handled first,
* and then run the user defined handlers. Return input is the
* q event is un-consumed else 0.
****************************************************************/
long
bit_handle_event(long dev, short val)
{
long ret = 0;
if ((ret = handle_const_q(dev, val)))
{
/* call handle_glq only if not const events */
ret = handle_GLQ(dev, val);
}
(void) fl_check_forms();
return ret;
}
/********************************************************************
* Wrapper to fl_qread: unlike fl_qread, bit_qread never blocks.
*******************************************************************/
long
bit_qread(short *val)
{
long dev;
int done = 0;
(void) fl_check_forms();
if (!fl_qtest())
{
return 0;
}
#ifdef MDEBUG
M_debug("Bit_Qread", "Events pending");
#endif
/*
* read event Q and handle it until no events left or there is something
* we do not know how to handle
*/
do
{
dev = fl_qread(val);
done = bit_handle_event(dev, *val);
}
while (!done && fl_qtest());
return dev;
}
/****************************************************************
* check if there is any q-event pending to be processed. This
* routine is called periodically to service the event Q.
****************************************************************/
void
check_emergency(void)
{
short val;
long dev;
/* if there is no Q pending, return */
if (!fl_check_forms() || !fl_qtest())
return;
/* note bit_qread remove all Q events until a unknown Q */
switch ((dev = bit_qread(&val)))
{
case ESCKEY:
if (val)
clean_up();
break;
case KEYBD:
if (val == 27)
clean_up();
break;
default:
/* eat it */
#ifdef MTRACE
M_trace("Emeg: ", "dev=%ld val=%d", dev, val);
#endif
break;
}
}
/************************************************************
* Pause an indefinate time until pause key is pressed again
************************************************************/
void
pausing(IPTR im)
{
long dev;
short val;
show_misc_info2("Paused");
fl_deactivate_all_forms();
do
{
(void) fl_check_forms();
dev = fl_qread(&val);
/*
* must not call bit_handle_event and its cousins, otherwise bad
* recursion
*/
if (dev == REDRAW && val)
repaint(im, val);
else if (dev == INPUTCHANGE && val)
set_current_window(val);
}
while (dev != PAUSEKEY || !val);
fl_activate_all_forms();
hide_misc_info2();
}
/***********************************************************************
* Read event queue within a time limit specified by milliseconds. Default
* returned value is def. Nagative or zero interval disables time-out.
* Originally used alarm/itimer and longjmp, but somehow, that combination
* screwed up the internal workings of FORMS. can't think of any reason why,
* but anyway, use of msleep actually simplified things a bit.
*
* Minimum allowed pause is about 20 milli-second
************************************************************************/
long
myqread(short *val, long def, long mseconds)
{
long dev = def;
unsigned int delta = 18;
int nd, i;
if (mseconds <= 0)
{
fl_check_forms();
while (!fl_qtest())
(void) fl_do_forms();
while (!(dev = fl_qread(val)))
;
return dev;
}
*val = win_id;
nd = mseconds / (delta + 2);
fl_check_forms();
for (i = (nd < 1 ? 1 : nd); --i >= 0;)
{
if (fl_qtest())
return fl_qread(val);
msleep(delta);
if ((i % 30) == 0)
fl_check_forms();
}
return def;
}